home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i033: Mail user's shell version 6.4, Part11/19
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Dan Heller <island!argv@sun.com>
- Posting-number: Volume 18, Issue 33
- Archive-name: mush6.4/part11
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 11 (of 19)."
- # Contents: cmd_help msgs.c
- # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:17 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'cmd_help' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cmd_help'\"
- else
- echo shar: Extracting \"'cmd_help'\" \(27197 characters\)
- sed "s/^X//" >'cmd_help' <<'END_OF_FILE'
- X/* @(#)cmd_help 1.4 10/24/88 (Dan heller) */
- X
- X%?%
- XThe `?' command will give you a list of legal commands. Most
- Xcommands accept -? as an option. This will give you specialized
- Xhelp with that particular command.
- X%%
- X
- X%ignore%
- X ignore/unignore [headers]
- X
- XUse this command to set the message headers you would like not
- Xto be printed when you read a message. If no header specified,
- Xthen a list of all headers currently being ignored is printed.
- XYou must specify a header for unignore.
- X
- XYou can set the variable "alwaysignore" to force normally
- Xignored headers to be ignored while saving messages, forwarding
- Xmessages or including messages into message buffers.
- X%%
- X
- X%set%
- X set/unset [variable [= value]]
- X
- XWith no parameters, set lists all variables and their values.
- XTo set a boolean variable (on or off), use:
- X set variable
- XTo set a variable's value to a string, use:
- X set variable = value
- X
- XIf you want double-quotes or white-space embedded in a string,
- Xencase the string in single quotes. If you want single quotes
- Xin a string, encase the string in double quotes.
- X
- XFor a list of all variables with special meanings, use:
- X set ?all
- XFor help on a particular one of these variables, use:
- X set ?variable_name
- X%%
- X
- X%readmsg%
- XYou can read messages in different ways. "type" and "print"
- Xwill print the current message. "top" will only print the first
- XN lines of the current message where N is the value of the
- Xvariable "crt". "next" will go to the next unread message and
- Xprint that. "previous" will go back and read the first unread
- Xmessage previous to the current. "^" will print the first
- Xmessage, "$" will print the last.
- X
- XAny of these commands can be followed by a message list, and
- Xeach message in that list will be printed (or piped to other
- Xcommands).
- X%%
- X
- X%alts%
- X alts [hostnames]
- X
- XThe alts command sets a list of hostnames on which you have an
- Xaccount. Normally, when you respond to all recipients of mail,
- Xyour account name will be listed as if you wished to send
- Xyourself mail. If you don't have metoo set, then your name will
- Xbe removed from the mailing list if your login name is on the
- Xlist and the host specified is in the alternates list. The
- Xspecial parameter `*' instructs alts to match all hostnames; in
- Xthat case, only the login name is tested.
- X%%
- X
- X%source%
- X source/saveopts [file]
- X
- XThe source/saveopts commands will load/save all variable
- Xsettings, options, aliases, cmd's, ignored headers ...
- Xeverything you can set, it loads or saves. The file read or
- Xwritten follows these rules:
- X
- X1) If a filename is given, that file is used
- X2) The file described by the environment variable MAILRC
- X3) In the user's home directory: .mushrc (if it exists)
- X4) In the user's home directory: .mailrc (if it exists)
- X
- XIf saveopts is used and the file exists, confirmation will be
- Xrequested before the file is overwritten.
- X%%
- X
- X%general%
- XThis is the general help message. To get help on a specific
- Xcommand, try "command -?". Extended help is given by typing
- X"help item" where item is one of:
- X path, msg_list, prompt, hdr_format
- XHelp with msg_list is highly advisable!
- X
- XType "?" to get a list of available commands. Try "? command"
- Xto get help on the particular command that you specify.
- X%%
- X
- X%path%
- XWhenever "path" is specified, the following syntax is legal
- Xbesides the normal path addressing scheme used by unix:
- X ~[user] -- the home directory of specified user (yours by default)
- X %[user] --/usr/spool/mail/login_name [user_name] (yours by default)
- X +file --the directory described by `set folder'; file is `file'
- X%%
- X
- X%msg_list%
- XA "msg_list" references one or more messages. The user
- Xspecifies a group of messages according to a special syntax.
- X
- X * All messages.
- X ^ The first message.
- X $ The last message.
- X . The current message.
- X N-M A range of messages between N and M, inclusive.
- X
- XIn the last case, N and M may be * ^ $ . or digits referencing
- Xexplicit message numbers. The range must be in ascending order.
- X
- XYou can also negate messages by placing the message list inside
- Xbraces, `{' `}' -- thus, the expression "2-19 {11-14}"
- Xreferences messages 2 through 19 except for those from 11
- Xthrough 14.
- X
- XCommands can be "piped" to one another, because the return value
- Xof a command is a msg_list, not text. For example,
- X pick -f fred | lpr
- Xwill find all messages "from fred" and send them to the printer.
- X
- XCommands dealing with more than one message process them in
- Xnumeric order -- not necessarily the order specified. Thus, the
- Xcommand "save 1-5 9 7 6 file" will save the messages in
- Xascending order, not in the order given.
- X%%
- X
- X%preserve%
- X preserve [msg_list]
- X
- XThe "preserve" command saves deleted or read messages in your
- Xmailbox. Without explicitely setting preserve, all mail that
- Xyou read will be saved in ~/mbox (or set mbox). Setting the
- Xboolean variable "hold" is equivalent to preserving each message
- Xas you read it.
- X%%
- X
- X%save%
- X save/write/copy [-s|-S|-a|-A] [!] [msg_list] [filename]
- X
- XIf no filename is specified, ~/mbox (or the value of the
- Xvariable "mbox") is used. Save and write will append msg if
- X`file' already exists. Specifying the `!' will overwrite the
- Xfile (e.g., erasing it first).
- X
- XTo save messages to a filename beginning with a digit, escape
- Xthe filename with a backslash (\).
- X
- XThe "write" command will write message without the headers (msg
- Xbody only). Save and write both mark messages for deletion
- Xunless "keepsave" is set. The "copy" command is identical to
- X"save" except that messages are not marked for deletion
- X(identical to having the variable "keepsave" set).
- X
- XThe -s and -S options save messages to files named by the
- Xsubject of the message. If more than one message is specified,
- Xthen the message subject of each message is used. If -S is
- Xspecified, then the subject of the first message is used for all
- Xmessages. Spaces and forward slashes (/) are converted to
- Xunderscores (_).
- X
- XThe -a and -A options save messages by author's login name.
- X%%
- X
- X%lpr%
- X lpr [-n] [-h] [msg_list]
- X -n print body of message only (not headers)
- X -h print all headers with message body (default true)
- X -Pxx print on printer xx
- X%%
- X
- X%respond%
- X replysender/replyall [msg_list] [-r path] [mail_flags] [users]
- X
- XThe "replysender" command replies only to the sender of a
- Xmessage, whereas "replyall" responds to everyone on the To: and
- XCc: lines of the message.
- X
- XThe commands "reply" is identical to "replysender".
- X
- XIf a message list is indicated, then each message on the list is
- Xreplied to in the same manner. If -r is specified with a host or
- Xpath (uucp-style), then each address in the list is routed via
- Xthis path. This overrides the value of auto_route (see man page).
- X
- XThe address of the author is obtained from certain headers in
- Xhis message to you. Unless you specify otherwise, mush will
- Xsearch for the headers Reply-To: Return-Path: and From:. You
- Xcan override these values by setting the variable reply_to_hdr.
- X
- X set reply_to_hdr = "sender reply-to return-path from_"
- X
- XThis example shows that mush will search for (in order), the
- Xheaders listed in the reply_to_hdr variable. If one header isn't
- Xfound, then mush looks for the next in the list. If none of the
- Xheaders in the list are found, the default headers (mentioned
- Xabove) are searched. The last header listed in the example is
- Xthe special "From " header. See the man page for more details.
- X
- XType "mail -?" for information on legal mail flags.
- X%%
- X
- X%sort%
- X sort [-] [a|d|R|s|S]
- X a by author (alphabetical)
- X d according to date
- X R by subject including Re: (alphabetical)
- X s by subject ignoring Re: (alphabetical)
- X S by status
- X
- XThe optional `-' flag will reverse the order of sorting. By
- Xdefault (no parameters), sort sorts messages by status: New,
- Xunread messages are first, followed by preserved messages and
- Xfinally the deleted messages are placed at the end.
- X
- XIf the "date_received" variable is set, sorting by date is
- Xdone using the date you received the message. Otherwise,
- Xmessages are sorted by date sent by the original author.
- X%%
- X
- X%pick%
- X pick [-x] [-f|s|t] [-h hdr] [-i] [-r msg_list] [<pat>]
- X [-d [-][date]] [-ago [n days] [n weeks] [n months]]
- X
- XSearch for patterns within messages. Entire messages are
- Xsearched for <pattern> unless -f, -h, -s, or -t is specified.
- XOnly one of -d, -f, -h, -s, -t and -ago can be specified; no
- Xpattern is used with -d and -ago.
- X
- X -x return those messages which do NOT match
- X -f match pattern in the "From:" field (author) only
- X -s match pattern in the "Subject:" header only
- X -t match pattern in the "To:" field only
- X -h hdr match pattern in specified header field only
- X -i ignore case of letters in when matching
- X -r msg_list restrict the range of messages search to msg_list
- X -d select messages sent on [+ after] [- before] date
- X A "date" is of the form: [+-][month]/[date[/year]]
- X Omitted fields default to today's values. Examples:
- X pick -d 4/20 messages on Apr 20, this year
- X pick -d -/2/85 on or before the 2nd, this month, 1985
- X pick -d +5/4 on or after May 4, this year
- X pick -d / finds today's messages only
- X At least one `/' char must be used in a date. There is
- X no strong date checking; 2/30 would be considered valid.
- X -ago select messages relative to the current date
- X Date formats for "ago" are more verbose than for -d; see
- X the manual page for details.
- X%%
- X
- X%alias%
- XOptions for alias:
- X alias print all namelists
- X alias name print namelist associated with name
- X alias name namelist set "name" to the value of namelist
- X unalias namelist unalias names in namelist
- X
- XA "namelist" consists of one or more addresses. An address may
- Xbe a name already set to another list, a valid user, a file or
- Xa program. Filenames must be full pathnames, i.e., they must
- Xbegin with a '/' (or with a ~, which expands to some home dir).
- XA "program" must start with a pipe symbol and be encased in
- Xquotes:
- X
- X "|program_name"
- X
- XThe command "expand" will print addresses (including sublists)
- Xassociated with the given alias.
- X%%
- X
- X%from%
- XWith no parameters, "from" will print the current message's
- Xheader line. If given a message list, "from" will print the
- Xheaders of the listed messages.
- X
- XThe special parameters `-' and `+' can be given to move the
- Xcurrent message pointer to the previous or next message
- Xrespectively, while also printing that message's header.
- X
- XIf a message list was given in addition to `-' or `+', then
- Xthe current message pointer will be set to the first or last
- Xmessage, respectively, in the message list given.
- X
- XExamples:
- X
- X from - 10-30 {16}
- Xwill print the headers of messages 10 through 30 except for
- Xmessage 16 and set the current message pointer to 10.
- X
- X pick -f Dan | from +
- Xwill print the headers of all messages that contain "Dan" in the
- Xauthor's name and set the current message pointer to the last
- Xone of that kind in the list.
- X
- X from +
- Xwill print the header of the message after the current message
- Xand increment the current message pointer to that message.
- X%%
- X
- X%own_hdrs%
- XThis command is used to set, unset or view your personalized
- Xmessage headers. These headers are included in all your
- Xoutgoing mail.
- X
- XOptions for my_hdr:
- X my_hdr show all headers
- X my_hdr header show value of header
- X my_hdr header: string set header to string
- X un_hdr header unset header
- X%%
- X
- X%fkey%
- XThis command is used to make function key settings in Suntools
- X(graphics) mode. When run as a tool (-t on command line),
- Xchoose the Options item, and the "function key" menu option.
- X%%
- X
- X%cmd%
- XThis function is used to establish command aliases; cmd's are
- Xjust like aliases in the C-shell. Options are:
- X cmd view all commands
- X cmd command show value of command
- X cmd command "value" set command to value
- X uncmd command unset command
- X
- XIf you want to reference history commands within a cmd,
- Xescape the ! with a backslash. For example:
- X
- X cmd r 'replysender \!* ; delete -t'
- X
- Xwill cmd "r" to reply using whatever parameters you have given on
- Xthe command line and then delete that message and print the next
- Xmessage (-t parameter to "delete").
- X%%
- X
- X%headers%
- X headers [+|-|N] [[-H]:c]
- X + print the next screenful (or use the 'z' command).
- X - print the previous screenful (or use 'z-' ).
- X N print a screenful starting at message number N.
- X -H:c where `c' is one of
- X a all messages (mostly for the command line parameter -H:c)
- X d deleted messages
- X n new messages
- X o old messages
- X p preserved messages
- X r replied-to messages
- X s saved messages
- X u unread messages
- X
- XThe "headers" command prints out a screenful of headers.
- XDeleted messages are not normally shown; set "show_deleted" to
- Xinclude deleted messages.
- X
- XThe command ":c" is equivalent to "headers -H:c". The -H can be
- Xomitted, i.e., "headers :c" will also work.
- X%%
- X
- X%hdr_format%
- XThis variable controls the display of message headers. Use:
- X set hdr_format="string"
- Xto change the header display. The string uses printf style
- Xformatting and follows these conventions:
- X %a address of the author
- X %c number of characters (bytes) in the message
- X %d entire date of the message (see "date_received" variable)
- X %f "From" field (author name and address)
- X %i the message-id (may or may not be present)
- X %l number of lines in the message
- X %M month name of the message
- X %N day of the month (number)
- X %n name of the author
- X %s subject of the message
- X %t "To" field (recipients)
- X %T time of the message (see "mil_time" variable)
- X %W day of the week (Sun, Mon, etc.)
- X %Y year of the message
- X %y year (last 2 digits only)
- X \n a newline
- X \t a tab
- X
- XA field specifier may be used in any % expansion. Thus, "%20s"
- Xwill print the first 20 characters of the Subject. No matter
- Xwhat the formatting string, the message number, the status of
- Xthe message and a '>' (if this is the "current" message) is
- Xbefore any user defined format is printed.
- X%%
- X
- X%folder%
- X folder/update [-N] [-r] [!] [%[user]|#|&|file]
- X -N Do not display the list of headers
- X -r read only mode (cannot write changes to this folder)
- X %[user] change to /usr/spool/mail/[user] (you by default)
- X # change to folder accessed previous to current folder
- X & change to "mbox" -- default is $mbox or ~/mbox
- X
- XThe "folder" command changes the current folder; with no parameters,
- Xit prints the name of the current folder. If `!' is specified, the
- Xcurrent folder is not updated before changing.
- X
- XThe "update" command updates the current folder. In this case, only
- Xthe -N and -r options are observed.
- X%%
- X
- X%prompt%
- XThis variable controls the prompt that mush will display.
- X set prompt = "string"
- XThe "string" follows printf style formatting conventions:
- X %F full path of the current working folder
- X %f name (path tail) of the current folder
- X %m current message number
- X %n number of new messages
- X %u number of unread messages
- X %d number of deleted messages
- X %t total number of messages
- X %T current time
- X %N day of the month (number) (today)
- X %W weekday name (today)
- X %M month name (this month)
- X %Y year (this year)
- X %y year (last 2 digits only)
- X \n newline
- X \t tab
- X%%
- X
- X%quit%
- X quit/exit
- X
- XThese commands end a mush session. "quit" will update your
- Xmailbox; if new mail has come in, you will be told so and given
- Xan option whether to really quit or not. "exit" will leave mush
- Xneither updating your mailbox nor checking for new mail.
- X%%
- X
- X%ls%
- XThe "ls" command is exactly like the UNIX command "ls". All
- Xparameters are the same. The variable "lister" can be set to
- Xa list of default parameters, thus avoiding having to specify
- Xthem all the time. The "folders" command is equivalent to
- Xdoing "ls $folder" from the Mush prompt.
- X%%
- X
- X%shell%
- X sh [command]
- X
- XIf a "command" is given, that UNIX command will be executed
- Xunder the Bourne shell. If no command is specified, then an
- Xinteractive shell will be started. The environment variable
- XSHELL or the local mail shell variable shell describes the
- Xshell to invoke. If none is set, then the default shell is
- Xdefined by the system administrator (currently set to csh).
- X
- XUsers on systems with job control will probably have little
- Xuse for the sh command.
- X%%
- X
- X%stop%
- XThe stop command sends a stop signal to the mail shell. It is
- Xequivalent to ^Z as it will stop the process. Since the shell
- Xnever needs to be exited, the command 'q' may be aliased to
- X"stop" and the shell may have
- X alias mail %mush
- X(assumes csh) which will bring mush into the foreground rather
- Xthan having to invoke a new shell. New mail will be read into
- Xthe shell automatically and much time and energy is saved.
- X%%
- X
- X%curses%
- XThe curses-based interface for Mush does not require a graphics
- Xdisplay, but does requires a terminal which can handle upline
- Xcursor movement capabilities. All commands are one or two
- Xkeystroke commands and are executed as soon as the key is typed.
- X
- XFor a list of current key-to-command bindings, use the "bind"
- Xcommand (defaults to 'b' in curses mode).
- X%%
- X
- X%bind%
- X bind <sequence> <curses-command> [ <parameters> ]
- X
- XBinding is done for the curses interface only. It allows the
- Xuser to bind keystrokes or key sequences to curses-interface
- Xcommands. You cannot bind keystrokes to regular mush commands
- Xusing bind.
- X
- XA bound key-sequence (input by the user) will be converted into
- Xthe curses command it is bound to. For a list of all curses
- Xcommands, issue the "bind" command and follow the instructions
- Xto get a list. Currently, parameters are ignored for all curses
- Xcommands except the special command "macro".
- X
- XWhen specifying sequences, you may enter almost anything at the
- Xkeyboard that you want to type. This includes most control
- Xcharacters. A special syntax is provided to specify control
- Xcharacters if you wish to set up default key bindings in your
- Xinitialization file without using real control characters.
- X
- XTo bind keystrokes that are control characters in the
- Xinitialization file, you must use the notation "\CX" where "X"
- Xis an upper-case letter representing the control key you want to
- Xuse. "\CN" would be control-N; "\n" is carriage return. You may
- Xnot bind keyboard generated signals; for most users, those key
- Xsequences are control-C and control-\. For users with job
- Xcontrol, the suspend characters (usually control-Z and
- Xcontrol-Y) are also ignored.
- X
- XTo specify the escape key, use "\E"; "\C[" will not work.
- X
- XTrying to bind a key sequence which prefixes another sequence is
- Xan error and the user is warned that the longer binding will not
- Xwork. The binding will take place, however, because it is
- Xpossible to unbind the shorter sequence, thus validating the
- Xlonger sequence.
- X
- XThe special curses command "macro" allows a string to be
- Xexecuted just as if the user typed it directly. Issue the
- X"bind-macro" command for more details.
- X%%
- X
- X%msg_flags%
- X flags [msg_list] [[+|-] [D N O P R S r U]]
- X
- XThis command displays the status of messages by default.
- XIf a list is specified, it will tell which bits of the
- Xmessage are set: Delete, New, Old, Preserved, Read, Saved
- Xreplied-to, and Unread. If any (one or more) of the bits
- Xare given and no + or - modifier is specified, then the
- Xstatus of each message in the list will be set to that
- Xstatus absolutely (other status flags are lost). However,
- Xif a + or - is specified, then the status is modified for
- Xthat bit to on (+) or off (-).
- X
- XIf no list is given, then the list of messages is taken
- Xfrom a pipe (if piped) or the current message is used.
- X%%
- X
- X%setenv%
- X setenv VARIABLE [value]
- X
- XVariable names may be any string, but traditionally environment
- Xvariables are all upper case. If no "value" is specified, then
- Xthe variable name will be set to an empty string. If the value
- Xcontains spaces, you should enclose the string in quotation
- Xmarks. Use printenv to print a list of all your environment
- Xvariables.
- X%%
- X
- X%unsetenv%
- X unsetenv VARIABLE
- X
- XYou must specify one and only one variable to unset in your
- Xenvironment variable settings. Use printenv to print a list of
- Xall your environment variables.
- X%%
- X
- X%edit_msg%
- X edit_msg [msg_list]
- X
- XThe "edit_msg" command lets you edit messages in your folder.
- XWhen editing messages, be careful not to remove certain message
- Xheaders such as Date:, From:, or any others that look important.
- XIf you remove or change something you shouldn't have, you will
- Xbe notified and the temporary file used to edit the message will
- Xnot be removed.
- X%%
- X
- X%bind-macro%
- X bind-macro [<sequence> [<expansion>]]
- X
- XThe "bind-macro" command allows you to set macros in curses
- Xmode, so that one keystroke (or a few) will act as though you
- Xhad typed a longer sequence. Using "bind-macro" is equivalent
- Xto specifying the "macro" special command as a parameter to
- Xthe "bind" command.
- X
- XGiven no parameters, "bind-macro" will list all current curses
- Xmode macros. Given only a <sequence>, it will show the current
- Xbinding for that sequence. Given both a <sequence> and an
- X<expansion>, it will create a macro such that, when the
- X<sequence> is typed in curses mode, the effect will be the same
- Xas if the <expansion> had been typed instead.
- X
- XThe same format for control characters that is used for the
- X"bind" command may be used in both the <sequence> and the
- X<expansion>, i.e.,
- X \Cx control-x (where x is a capital letter)
- X \E the escape character (\C[ does NOT work!)
- X \n a newline (other C-style escapes also work)
- X
- XExample:
- X bind-macro F [folder]+record\n
- X
- XIf you are in curses mode and hit the F key, then the curses
- Xmode command "folder" will execute and +record (followed by
- Xa carriage return) will be entered as if you typed it.
- X
- XAlso see the "map" and "map!" commands.
- X%%
- X
- X%map%
- X map [<sequence> [<expansion>]]
- X
- XThe "map" command allows you to use one keystroke (or a few) and
- Xhave it act as though you had typed a longer sequence.
- X
- XGiven no parameters, "map" will list all current line mode
- Xmacros. Given only a <sequence>, it will show the current
- Xbinding for that sequence. Given both a <sequence> and an
- X<expansion>, it will create a macro such that, when the
- X<sequence> is typed in line mode, the effect will be the same
- Xas if the <expansion> had been typed instead.
- X
- XThe same format for control characters that is used for the
- X"bind" command may be used in both the <sequence> and the
- X<expansion>, i.e.,
- X \Cx control-x (where x is a capital letter)
- X \E the escape character (\C[ does NOT work!)
- X \n a newline (other C-style escapes also work)
- X
- XExample:
- X map & print\n
- X
- XIf you are not in curses mode and hit the & key, then it will
- Xbe as if you typed the word "print" and hit carriage return.
- X
- XTo type a character without having the mapping expanded, precede
- Xthe character with a backslash (\).
- X
- XAlso see the "map!" and "bind" commands.
- X%%
- X
- X%map!%
- X map! [<sequence> [<expansion>]]
- X
- XThe "map!" command allows you to set macros in message
- Xcomposition mode, so that one keystroke (or a few) will act
- Xas though you had typed a longer sequence. map!'s take
- Xeffect regardless of whether you started the letter from
- Xcurses mode or line mode.
- X
- XGiven no parameters, "map!" will list all composition mode
- Xmacros. Given only a <sequence>, it will show the current
- Xbinding for that sequence. Given both a <sequence> and an
- X<expansion>, it will create a macro such that, when the
- X<sequence> is typed in message composition mode, the effect will
- Xbe the same as if the <expansion> had been typed instead.
- X
- XThe same format for control characters that is used for the
- X"bind" command may be used in both the <sequence> and the
- X<expansion>, i.e.,
- X \Cx control-x (where x is a capital letter)
- X \E the escape character (\C[ does NOT work!)
- X \n a newline (other C-style escapes also work)
- X
- XExample:
- X map! ! <BANG>
- X
- XIf you are typing in a letter regardless of which interface you
- Xuse and you hit the ! key, then it would be as if you typed the
- Xkeys "<BANG>".
- X
- XTo type a character without having the mapping expanded, precede
- Xthe character with a backslash (\).
- X
- XAlso see the "bind" and "map" commands.
- X%%
- X
- X%eval%
- X eval args ...
- X
- XThis command causes its arguments to be re-parsed and then
- Xexecuted as a mush command. Example:
- X set initprompt='"$hostname:$cwd "'
- X eval set prompt=$initprompt
- X%%
- X
- X%pipe_msg%
- X pipe [msg-list] unix-command
- X
- XThe specified unix-command is executed. The standard input of
- Xthe command is the texts of listed messages, including headers
- Xthat are not ignored (see "ignore -?" and "set ?show_hdrs"). If
- Xthis command is part of a mush pipeline (|) then any list of
- Xmessages given is added to those taken from the pipeline. If no
- Xmsg-list is given and there is no pipeline, the current message
- Xis used. The unix-command is executed via "sh", so csh aliases
- Xmay not be used.
- X
- XIf invoked with a capital letter (Pipe), only the bodies of the
- Xmessages will be fed to the unix-command -- all headers will be
- Xomitted.
- X
- XExamples:
- X pipe 2 7 more -- send messages 2 and 7 through "more"
- X pipe patch -- send the current message to "patch"
- X 1 | Pipe nroff -- send the body of message 1 to "nroff"
- X%%
- X
- X%merge%
- X merge [-N] folder-name
- X
- XThe contents of the specified folder are read into the current
- Xfolder. If -N is not specified, a header summary is printed
- Xfor each message read (see "headers -?").
- X
- XA list of all the merged messages is returned for use in pipes.
- X%%
- X
- X%echo%
- X echo [-n] [-h | -p] args
- X
- XEcho simply echoes the parameters to the command back to the user.
- X
- XIf the -n flag is given, then no newline is appended.
- XIf the -h flag is given, then echo looks for formatting parameters
- Xas if the "from" command were given on the "current" message.
- XIf the -p flag is given, then echo looks for formatting parameters
- Xas if your prompt were changed temporarily.
- X
- XExamples:
- X echo -h This message is from %a and is dated %d
- Xmight produce:
- X This message is from island!argv and is dated Dec 14, 1988.
- X
- X echo -p There are %n new messages to read in %f.
- Xmight produce:
- X There are 5 new messages to read in /usr/spool/mail/argv.
- X
- XNote that -h and -p cannot be specified together.
- X%%
- X
- X%undigest%
- X undigest [-m] [msg_list] [filename]
- X
- XA "digest" is a mail message which is a collection of other mail messages
- Xmailed to a "moderator" by other users. The moderator compiles all the
- Xmessages into a folder and sends the result to all the subscribers of the
- Xmailing list. The undigest command disassembles the entries into the set
- Xof messages which comprises the digest.
- X
- XThe -m option will merge these messages into the current folder. Otherwise,
- Xif a filename is specified, a new folder is created and the user can change
- Xfolders to read the messages separately.
- X
- XIf a message list is specified, each digest is disassembled to the same
- Xfilename (if given). If no filename is given and the user did not request
- Xa merge, then a folder is created based on the subject of the digest.
- X%%
- END_OF_FILE
- if test 27197 -ne `wc -c <'cmd_help'`; then
- echo shar: \"'cmd_help'\" unpacked with wrong size!
- fi
- # end of 'cmd_help'
- fi
- if test -f 'msgs.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'msgs.c'\"
- else
- echo shar: Extracting \"'msgs.c'\" \(24063 characters\)
- sed "s/^X//" >'msgs.c' <<'END_OF_FILE'
- X/* @(#)msgs.c (c) copyright 10/18/86 (Dan Heller) */
- X
- X#include "mush.h"
- X
- Xvoid
- Xdisplay_msg(n, flg)
- Xregister int n;
- Xlong flg;
- X{
- X if (ison(msg[n].m_flags, DELETE) && !do_set(set_options, "show_deleted")) {
- X print("Message %d deleted; ", n+1);
- X#ifdef SUNTOOL
- X if (istool)
- X print_more("Select UNDELETE to read."), do_clear();
- X else
- X#endif /* SUNTOOL */
- X if (iscurses)
- X print_more("Type 'u' to undelete.");
- X else
- X print("Type 'undelete %d' to undelete\n", n+1);
- X return;
- X }
- X set_isread(n);
- X if (ison(flg, M_TOP)) {
- X turnon(flg, NO_HEADER);
- X print("Top of "), turnon(glob_flags, CONT_PRNT);
- X }
- X
- X#ifdef MMDF
- X turnon(flg, NO_SEPARATOR);
- X#endif /* MMDF */
- X if (!istool && isoff(flg, NO_PAGE) &&
- X crt < msg[n].m_lines && isoff(flg, M_TOP)) {
- X char buf[32], *pager = do_set(set_options, "pager");
- X if (!pager)
- X pager = DEF_PAGER;
- X if (!*pager || !strcmp(pager, "internal"))
- X pager = NULL; /* default to internal pager if pager set to "" */
- X (void) do_pager(pager, TRUE); /* start pager */
- X (void) do_pager(sprintf(buf, "Message #%d (%d lines)\n",
- X n+1, msg[n].m_lines), FALSE);
- X (void) copy_msg(n, NULL_FILE, flg);
- X (void) do_pager(NULL, FALSE); /* end pager */
- X } else {
- X print("Message #%d (%d lines)\n", n+1, msg[n].m_lines);
- X (void) copy_msg(n, stdout, flg);
- X }
- X}
- X
- X/*
- X * copy message 'n' to file "fp" according to various flag arguments
- X * return number of lines copied or -1 if system error on fputs.
- X * If "fp" is null, send to internal pager. This can only happen from
- X * display_msg above.
- X */
- Xcopy_msg(n, fp, flags)
- Xregister int n;
- Xregister FILE *fp;
- Xu_long flags;
- X{
- X register int ignoring = 0, lines = 0;
- X register char *indent_str;
- X int on_hdr = 1, top, squeeze = 0;
- X char line[BUFSIZ], *show_hdrs = NULL;
- X
- X still_more = 0;
- X if (ison(flags, M_TOP)) {
- X register char *p = do_set(set_options, "toplines");
- X top = (p)? atoi(p) : crt;
- X }
- X /* When updating to a folder, always write all headers! */
- X if (ison(flags, UPDATE_STATUS))
- X turnon(flags, NO_IGNORE);
- X else if (do_set(set_options, "alwaysignore"))
- X turnoff(flags, NO_IGNORE);
- X if (isoff(flags, NO_IGNORE)) {
- X if (do_set(set_options, "squeeze"))
- X squeeze = 1;
- X show_hdrs = do_set(set_options, "show_hdrs");
- X }
- X
- X#ifdef SUNTOOL
- X if (istool && (!fp || fp == stdout)) {
- X register int x = (msg[n].m_lines + 2) * l_height(curfont);
- X
- X if (x > 32765) { /* to overcome a bug in pixrects that sun won't fix */
- X print("message too big to display using this font");
- X return 0;
- X }
- X if (x < msg_rect.r_height) /* make it at least as big as the window */
- X x = msg_rect.r_height;
- X /* If the window isn't big enough, an infinite loop occurs in Addstr */
- X if (x < 2 * l_height(curfont) || msg_rect.r_width < 3*l_width(curfont))
- X return 0;
- X do_clear();
- X lock_cursors();
- X /* msg_pix is for Addstr() */
- X if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) {
- X error("mem_create");
- X return 0;
- X }
- X pr_rop(msg_pix, 0,0, msg_rect.r_width-1, x-1, PIX_CLR, 0,0,0);
- X on_hdr = 1;
- X }
- X#endif /* SUNTOOL */
- X if (ison(flags, INDENT)) {
- X if ((indent_str = do_set(set_options, "pre_indent_str"))) {
- X char *old_fmt = hdr_format;
- X hdr_format = indent_str;
- X fprintf(fp, "%s\n", compose_hdr(n) + 9); /* magic number 9 !! */
- X hdr_format = old_fmt;
- X }
- X if (!(indent_str = do_set(set_options, "indent_str")))
- X indent_str = DEF_INDENT_STR;
- X }
- X /* "line" used as dummy here, since 0 bytes read */
- X if (!msg_get(n, line, 0)) {
- X error("Unable to find msg %d", n+1);
- X return -1;
- X }
- X while (still_more < msg[n].m_size && fgets(line, sizeof (line), tmpf)) {
- X still_more += strlen(line);
- X#ifdef MMDF
- X if (ison(flags, NO_SEPARATOR)) {
- X if (!strncmp(line, MSG_SEPARATOR, 4))
- X continue;
- X }
- X#endif /* MMDF */
- X /*
- X * If squeeze is one, all blanks lines squeeze down to one blank line.
- X * If squeeze is two, squeezing is in progress so wait for the next \n.
- X */
- X if (*line == '\n') {
- X if (on_hdr) /* blank line -- end of header */
- X turnoff(flags, NO_HEADER), on_hdr = 0;
- X if (squeeze > 1)
- X continue;
- X else if (squeeze)
- X squeeze = 2;
- X } else if (squeeze > 1)
- X squeeze = 1;
- X
- X if (ison(flags, UPDATE_STATUS))
- X if (!strncmp(line, "Status:", 7))
- X continue; /* ignore this and other "Status" lines */
- X else if (!on_hdr) {
- X /* preserve NEW/UNREAD status on preserved messages */
- X register char *p = line;
- X p += Strcpy(p, "Status: O");
- X if (isoff(msg[n].m_flags, UNREAD) &&
- X isoff(msg[n].m_flags, PRESERVE))
- X *p++ = 'R';
- X if (ison(msg[n].m_flags, SAVED))
- X *p++ = 'S';
- X if (ison(msg[n].m_flags, REPLIED))
- X *p++ = 'r';
- X *p++ = '\n', *p = 0;
- X fputs(line, fp);
- X (void) strcpy(line, "\n");
- X turnoff(flags, UPDATE_STATUS);
- X }
- X if (on_hdr && (isoff(flags, NO_IGNORE) || ison(flags, FORWARD))) {
- X register char *p = any(line, " \t:");
- X if (!p)
- X ignoring = 0, on_hdr = 0;
- X else if (ignoring)
- X if (*p != ':') {
- X Debug("Ignoring: %s", line);
- X continue;
- X } else
- X ignoring = 0;
- X if (p && *p == ':') {
- X *p = 0;
- X ignoring = 0;
- X if (show_hdrs) {
- X if (!chk_two_lists(line, show_hdrs, ":, \t"))
- X ignoring = 1;
- X } else if (ison(flags, FORWARD)) {
- X if (chk_two_lists(line, IGNORE_ON_FWD, ":, \t"))
- X ignoring = 1;
- X } else {
- X register struct options *opts;
- X for (opts = ignore_hdr; opts; opts = opts->next)
- X if (!lcase_strncmp(opts->option, line, -1)) {
- X ignoring = 1;
- X break;
- X }
- X }
- X *p = ':';
- X if (ignoring) {
- X Debug("Ignoring: %s", line);
- X continue;
- X }
- X }
- X }
- X if (!on_hdr && ison(flags, M_TOP) && !--top)
- X break;
- X if (isoff(flags, NO_HEADER)) {
- X /* note that function returns the number of lines */
- X lines++;
- X#ifdef SUNTOOL
- X if (istool && (!fp || fp == stdout)) {
- X Addstr(line);
- X continue;
- X }
- X#endif /* SUNTOOL */
- X if (ison(flags, INDENT))
- X fputs(indent_str, fp);
- X if (!fp) {
- X if (do_pager(line, FALSE) == EOF)
- X return -1;
- X } else if (fputs(line, fp) == EOF)
- X /* Pipe broken, out of file space, etc */
- X return -1;
- X }
- X }
- X if (ison(flags, INDENT) &&
- X (indent_str = do_set(set_options, "post_indent_str")) && *indent_str) {
- X char *old_fmt = hdr_format;
- X hdr_format = indent_str;
- X fprintf(fp, "%s\n", compose_hdr(n)+9); /* magic number 9 !! */
- X hdr_format = old_fmt;
- X }
- X#ifdef SUNTOOL
- X if (istool && (!fp || fp == stdout)) {
- X unlock_cursors();
- X txt.y = still_more = msg_rect.r_height;
- X scroll_win(0); /* causes a display */
- X }
- X#endif /* SUNTOOL */
- X return lines;
- X}
- X
- X/*
- X * copy tempfile back to folder.
- X * Return 1 on success, 0 on failure.
- X */
- Xcopyback(prompt)
- Xchar *prompt;
- X{
- X register int i=0, j=0, k=0;
- X register long flg = 0;
- X register FILE *mbox = NULL_FILE, *mail_fp = NULL_FILE;
- X#ifndef DOT_LOCK
- X#ifdef SYSV
- X FILE *save_mail_fp = NULL_FILE;
- X#endif /* SYSV */
- X#endif /* !DOT_LOCK */
- X char *mbox_file, action = 0;
- X int hold = 0, delete_it = 0, dont_unlink = FALSE;
- X int isspool, keepsave;
- X static int first = 1;
- X
- X /*
- X * if there is new mail in this folder, the user is notified and
- X * prompted if he really wants to update the folder. He's either
- X * quitting or changing folders, so let him read the new mail first.
- X */
- X if (!first && check_new_mail() > 0) {
- X if (!istool) {
- X char buf[16];
- X if (iscurses)
- X putchar('\n'), turnon(glob_flags, CNTD_CMD);
- X print("%s [n] ", prompt);
- X buf[0] = 0;
- X if (!Getstr(buf, sizeof (buf), 0) || lower(*buf) != 'y')
- X return 0;
- X }
- X }
- X first = 0;
- X
- X /* If the user hasn't changed anything, just return true */
- X if (isoff(glob_flags, DO_UPDATE))
- X return 1;
- X if (ison(glob_flags, READ_ONLY)) {
- X print("Unable to update %s: read only\n", mailfile);
- X return 0; /* user should use "exit" instead of "quit". */
- X }
- X if (!msg_cnt) /* prevent unnecessary overwrite */
- X return 1;
- X
- X#ifdef SUNTOOL
- X if (istool) {
- X timerclear(&(mail_timer.it_interval));
- X timerclear(&(mail_timer.it_value));
- X }
- X#endif /* SUNTOOL */
- X
- X /* open mbox if: "autodelete" AND "hold" are NOT set. */
- X if (!strcmp(mailfile, spoolfile)
- X && !(delete_it = !!do_set(set_options, "autodelete"))
- X && !(hold = !!do_set(set_options, "hold"))) {
- X register char *p;
- X int x = 1; /* tell getpath to ignore "ENOENT" if file not found */
- X
- X if (!(p = do_set(set_options, "mbox")))
- X p = DEF_MBOX;
- X mbox_file = getpath(p, &x);
- X if (x) {
- X if (x > 0)
- X print("%s is a directory.\n", mbox_file);
- X else
- X print("Unable to open %s: %s\n", p, mbox_file);
- X mbox = NULL_FILE;
- X } else {
- X if (Access(mbox_file, F_OK) == -1) /* does it exist? */
- X mbox = mask_fopen(mbox_file, "w");
- X else
- X mbox = mask_fopen(mbox_file, "a");
- X if (!mbox)
- X error("Unable to write to %s", mbox_file);
- X }
- X }
- X#ifdef DOT_LOCK
- X if ((i = dot_lock(mailfile)) == 0)
- X#endif /* DOT_LOCK */
- X#ifdef DOT_LOCK
- X mail_fp = mask_fopen(mailfile, "w+");
- X#else /* !DOT_LOCK */
- X /* We can't lock a file unless we have an fd, but "w+" will zero
- X * the file. If the lock later failed for any reason (possible
- X * race condition with an MTA), we would lose all current mail.
- X * So, open read/write (if possible) and truncate later.
- X */
- X mail_fp = mask_fopen(mailfile, "r+");
- X#endif /* DOT_LOCK */
- X if (!mail_fp) {
- X error("Unable to rewrite %s", mailfile);
- X if (mbox)
- X fclose(mbox);
- X return 0;
- X }
- X if (i != 0 || lock_file(mailfile, mail_fp) == -1) {
- X#ifndef DOT_LOCK
- X error("WARNING: unable to lock %s", mailfile);
- X#endif /* DOT_LOCK */
- X if (mail_fp)
- X close_lock(mailfile, mail_fp);
- X if (mbox)
- X fclose(mbox);
- X return 0;
- X }
- X#if !defined(DOT_LOCK) && defined(SYSV)
- X /* SysV can't truncate a file in the middle, so we can't just
- X * write to mail_fp and close. Instead, we save the mail_fp
- X * and reopen for writing, ignoring our own lock. After updating,
- X * we can safely fclose both file pointers.
- X */
- X save_mail_fp = mail_fp;
- X /* This could fail if we run out of file descriptors */
- X if (!(mail_fp = fopen(mailfile, "w"))) {
- X error("WARNING: unable to reopen %s for update", mailfile);
- X if (save_mail_fp)
- X close_lock(mailfile, save_mail_fp);
- X if (mbox)
- X fclose(mbox);
- X return 0;
- X }
- X#endif /* SYSV && !DOT_LOCK */
- X
- X print("Updating \"%s\"", mailfile);
- X
- X turnon(flg, UPDATE_STATUS);
- X turnon(glob_flags, IGN_SIGS);
- X
- X keepsave = !!do_set(set_options, "keepsave");
- X isspool = !strcmp(mailfile, spoolfile);
- X
- X for (i = 0; i < msg_cnt; i++)
- X /* check to see if message is marked for deletion or, if read and not
- X * preserved, delete it if autodelete is set. Otherwise, save the
- X * message in the spool file if hold is set. If all fails, save in mbox.
- X */
- X if (ison(msg[i].m_flags, DELETE)
- X || ison(msg[i].m_flags, SAVED) && !keepsave &&
- X isoff(msg[i].m_flags, PRESERVE) && isspool
- X || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE)
- X && delete_it) {
- X Debug("%s %d",
- X (action!='d')? "\ndeleting message:" : "", i+1), action = 'd';
- X continue;
- X } else if (ison(msg[i].m_flags, UNREAD) ||
- X ison(msg[i].m_flags, PRESERVE) || hold || !mbox) {
- X j++;
- X Debug("%s %d",
- X (action!='s')? "\nsaving in spool:" : "", i+1), action = 's';
- X if (copy_msg(i, mail_fp, flg) == -1) {
- X error("WARNING: unable to write back to spool");
- X print("ALL mail left in %s\n", tempfile);
- X print("Spool mailbox may be corrupted.\n");
- X dont_unlink = TRUE;
- X break;
- X }
- X } else if (isspool) { /* copy back to mbox */
- X k++;
- X if (copy_msg(i, mbox, flg) == -1) {
- X error("WARNING: unable to write to mbox");
- X print("Unresolved mail left in %s\n", tempfile);
- X dont_unlink = TRUE;
- X break;
- X }
- X Debug("%s %d",
- X (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm';
- X }
- X Debug("\n%s", mailfile);
- X
- X#ifndef DOT_LOCK
- X#ifdef SYSV
- X /* Close the write file pointer first */
- X fclose(mail_fp);
- X mail_fp = save_mail_fp;
- X#else /* !SYSV */
- X /* Truncate the file at the end of what we just wrote.
- X * If you aren't SYSV and you still can't ftruncate(),
- X * you're out of luck?
- X */
- X (void) ftruncate(fileno(mail_fp), ftell(mail_fp));
- X#endif /* SYSV */
- X#endif /* !DOT_LOCK */
- X
- X close_lock(mailfile, mail_fp);
- X
- X#ifdef SUNTOOL
- X if (istool) {
- X mail_timer.it_value.tv_sec = time_out;
- X setitimer(ITIMER_REAL, &mail_timer, NULL);
- X }
- X#endif /* SUNTOOL */
- X
- X /* some users like to have zero length folders for frequent usage */
- X if (mbox)
- X fclose(mbox);
- X if (j) {
- X long times[2];
- X times[1] = time(×[0]) - (long)2;
- X if (!strcmp(mailfile, spoolfile) && utime(mailfile, times))
- X error("utime");
- X print_more(": saved %d message%s\n", j, (j==1)? NO_STRING: "s");
- X } else
- X#ifdef HOMEMAIL
- X if (!dont_unlink && !do_set(set_options, "save_empty"))
- X#else /* HOMEMAIL */
- X if (strcmp(mailfile, spoolfile) && !dont_unlink &&
- X !do_set(set_options, "save_empty"))
- X#endif /* HOMEMAIL */
- X if (unlink(mailfile))
- X turnon(glob_flags, CONT_PRNT), error(": cannot remove");
- X else
- X print_more(": removed\n");
- X else
- X print_more(": empty\n");
- X if (k)
- X print("saved %d message%s in %s\n",k,(k==1)? NO_STRING:"s", mbox_file);
- X
- X turnoff(glob_flags, IGN_SIGS);
- X
- X return 1;
- X}
- X
- X/*
- X * check the sizes of the current folder (file) and the spool file.
- X * spool_size is the size in bytes of the user's main mailbox.
- X * last_size is the size of the _current_ folder the last time we checked.
- X * return true if the current folder has new mail. check_new_mail() checks
- X * for new mail in the system mailbox since it checks against last_spool_size.
- X */
- Xmail_size()
- X{
- X struct stat buf;
- X if (strcmp(mailfile, spoolfile) && !stat(spoolfile, &buf))
- X spool_size = buf.st_size;
- X if (!*mailfile)
- X return 0;
- X if (stat(mailfile, &buf)) {
- X if (errno != ENOENT)
- X error("Unable to stat %s", mailfile);
- X return 0;
- X }
- X if (!strcmp(mailfile, spoolfile))
- X spool_size = buf.st_size;
- X if (buf.st_size != last_size) {
- X last_size = buf.st_size;
- X return 1;
- X }
- X return 0;
- X}
- X
- Xvoid
- Xmail_status(as_prompt)
- X{
- X static char buf[256];
- X register int cnt = 0, new = 0, unread = 0, deleted = 0;
- X
- X for ( ; cnt < msg_cnt; cnt++) {
- X if (ison(msg[cnt].m_flags, UNREAD))
- X unread++;
- X if (ison(msg[cnt].m_flags, DELETE))
- X deleted++;
- X if (isoff(msg[cnt].m_flags, OLD))
- X new++;
- X }
- X if (as_prompt) {
- X register char *p, *b = buf;
- X for (p = prompt; *p; p++)
- X if (*p == '\\')
- X switch (*++p) {
- X case 'n': case 'r': *b++ = '\n';
- X when 't': *b++ = '\t';
- X otherwise: *b++ = *p;
- X }
- X else if (*p == '%')
- X switch (*++p) {
- X case 'm':
- X b += strlen(sprintf(b,"%d",(msg_cnt)? current_msg+1:0));
- X when 't':
- X b += strlen(sprintf(b, "%d", msg_cnt));
- X when 'd':
- X b += strlen(sprintf(b, "%d", deleted));
- X when 'u':
- X b += strlen(sprintf(b, "%d", unread));
- X when 'n':
- X b += strlen(sprintf(b, "%d", new));
- X when 'f':
- X {
- X char *tail = rindex(mailfile, '/');
- X if (tail && tail[1])
- X b += Strcpy(b, tail+1);
- X else
- X /* Fall through */
- X case 'F':
- X b += Strcpy(b, mailfile);
- X if (ison(glob_flags, READ_ONLY))
- X b += Strcpy(b, " [read-only]");
- X }
- X when 'T': case 'D': case 'Y': case 'y':
- X case 'M': case 'N': case 'W':
- X b += Strcpy(b, Time(p, (long)0));
- X otherwise: *b++ = *p;
- X }
- X else if (*p == '!')
- X b += strlen(sprintf(b, "%d", hist_no+1));
- X else
- X *b++ = *p;
- X *b = 0;
- X print("%s", buf); /* use %s in case "buf" has any %'s in it */
- X return;
- X }
- X (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread",
- X mailfile, ison(glob_flags, READ_ONLY)? " [read only]" : "",
- X msg_cnt, (msg_cnt != 1)? "s": NO_STRING, new, unread);
- X if (istool || iscurses)
- X (void) sprintf(buf+strlen(buf), ", %d deleted", deleted);
- X#ifdef SUNTOOL
- X if (istool) {
- X static char ic_text[4];
- X extern struct pixrect mail_icon_image1, mail_icon_image2;
- X (void) sprintf(ic_text, "%3d", msg_cnt);
- X tool_set_attributes(tool,
- X WIN_LABEL, buf,
- X WIN_ICON_LABEL, ic_text,
- X WIN_ICON_IMAGE, ison(glob_flags, NEW_MAIL)?
- X &mail_icon_image2 : &mail_icon_image1,
- X 0);
- X } else
- X#endif /* SUNTOOL */
- X#ifdef CURSES
- X if (iscurses) {
- X move (0, 0);
- X printw("%-3d %-.*s",
- X ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol();
- X } else
- X#endif /* CURSES */
- X puts(buf);
- X return;
- X}
- X
- X/*
- X * For uucp mailers that use >From lines with "remote from <path>":
- X * (where "path" is a hostname or pathnames)
- X *
- X * a. Set the return_path to the empty string.
- X * b. For each From_ or >From_ line:
- X * c. Save the username (second token).
- X * d. Save the date (3-7 tokens).
- X * e. If it has a "remote from" then append the remote host
- X * (last token) followed by a "!" to the return_path.
- X * f. If the saved username has a '@' but no '!' then convert it
- X * to UUCP path form.
- X * g. Append the saved username to return_path.
- X */
- Xparse_from(fp, path)
- XFILE *fp;
- Xchar path[];
- X{
- X char user[256], buf[256]; /* max size for each line in a mail file */
- X register char *p;
- X long save_offset = ftell(fp);
- X
- X path[0] = '\0';
- X while (fgets(buf, sizeof buf, fp)) {
- X if (strncmp(buf, ">From ", 6))
- X break;
- X p = buf + 6;
- X
- X (void) sscanf(p, "%s", user);
- X
- X while (p = index(p+1, 'r')) {
- X if (!strncmp(p, "remote from ", 12)) {
- X char *p2 = path+strlen(path);
- X skipspaces(12);
- X sscanf(p, "%s", p2); /* add the new machine to current path */
- X (void) strcat(p2, "!");
- X break;
- X }
- X }
- X
- X if (p)
- X (void) bang_form(path + strlen(path), user);
- X save_offset = ftell(fp);
- X }
- X fseek(fp, save_offset, L_SET);
- X}
- X
- X/*
- X * Scan a file and select messages from it and append them to the current folder
- X *
- X * If "append" is 1, start where we left off (held in msg[cnt].m_offset)
- X * and scan for messages. Append all messages found until EOF.
- X *
- X * If "append" is 2, we're merging in a new file, so start at the end of
- X * the present folder and append all messages found until EOF.
- X *
- X * If "append" is 0, then the message separator must exist once and
- X * only once. All extra occurrences of the separator is preceded by a '>'.
- X * The list argument will be the message number to replace in the current
- X * folder with the message read in from other filename.
- X */
- Xload_folder(file, append, list)
- Xchar *file, *list;
- Xint append;
- X{
- X char buf[BUFSIZ];
- X int lines = 0, msg_found = 0, had_error = 1;
- X int get_status = 1, cnt;
- X long bytes, ftell();
- X struct msg old;
- X char wkday[4], month[4];
- X int day, year, mins, hour;
- X FILE *fp;
- X#ifdef MMDF
- X int begin_sep = 0; /* track beginning vs ending separators */
- X#endif /* MMDF */
- X
- X if (!(fp = fopen(file, "r"))) {
- X error("Unable to open %s", file);
- X return -1;
- X }
- X
- X if (append) {
- X cnt = msg_cnt;
- X (void) fseek(fp, append == 1 ? msg[cnt].m_offset : 0L, L_SET);
- X } else {
- X cnt = (int)list;
- X old = msg[cnt];
- X }
- X
- X if (isoff(glob_flags, READ_ONLY)) {
- X if (tmpf)
- X (void) fclose(tmpf);
- X if (!(tmpf = mask_fopen(tempfile, "a"))) {
- X error("Unable to open %s for appending", tempfile);
- X (void) fclose(fp);
- X return -1;
- X }
- X (void) fseek(tmpf, 0L, 2); /* assure we're at the end of the file */
- X } else if (append == 2) {
- X /* you can't merge in a folder to a read-only folder */
- X (void) fclose(fp);
- X return -1;
- X }
- X
- X#ifdef MMDF
- X if (!append) {
- X strcpy(buf, MSG_SEPARATOR);
- X goto do_headers;
- X }
- X#endif /* MMDF */
- X while (fgets(buf, sizeof (buf), fp)) {
- X#ifndef MSG_SEPARATOR
- X if (!strncmp(buf, "From ", 5) &&
- X /* From uucp Wed Jan 11 20:40:00 1989 */
- X (sscanf(buf+5, "%*s %3s %3s %d %d:%d:%*d %d",
- X wkday, month, &day, &hour, &mins, &year) == 6 ||
- X /* From uucp Wed Jan 11 20:40:00 PST 1989 */
- X sscanf(buf+5, "%*s %3s %3s %d %d:%d:%*d %*s %d",
- X wkday, month, &day, &hour, &mins, &year) == 6 ||
- X /* From uucp Wed Jan 11 20:40 PST 1989 */
- X sscanf(buf+5, "%*s %3s %3s %d %d:%d %*s %d",
- X wkday, month, &day, &hour, &mins, &year) == 6))
- X#else /* MSG_SEPARATOR */
- X if (!strncmp(buf, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
- X#endif /* MSG_SEPARATOR */
- X {
- X#ifdef MMDF
- X if (!append)
- X fputc('>', tmpf);
- X else if (begin_sep = !begin_sep)
- Xdo_headers:
- X#else /* MMDF */
- X if (!append && msg_found)
- X fputc('>', tmpf);
- X else
- X#endif /* MMDF */
- X {
- X msg_found++;
- X had_error = 0;
- X if (append && cnt == MAXMSGS-2) {
- X wprint("WARNING: exceeded %d messages.\n", MAXMSGS);
- X wprint("Not all messages have been loaded.\n");
- X had_error++;
- X break;
- X }
- X if (ison(glob_flags, READ_ONLY))
- X bytes = ftell(fp) - strlen(buf);
- X else {
- X char path[256];
- X parse_from(fp, path);
- X if (path[0])
- X (void) sprintf(buf, "From %s %s %s %d %d:%d:00 %d\n",
- X path, wkday, month, day, hour, mins, year);
- X bytes = ftell(tmpf);
- X }
- X /* finish up message structure from previous message.
- X * if this is incorporating new mail, check "lines" to
- X * see if previous message has already been set!
- X */
- X if (cnt && lines) {
- X msg[cnt-1].m_size = bytes - msg[cnt-1].m_offset;
- X msg[cnt-1].m_lines = lines;
- X }
- X if (isoff(glob_flags, READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X msg[cnt].m_offset = bytes;
- X msg[cnt].m_flags = 0L;
- X lines = 0;
- X#ifndef MSG_SEPARATOR
- X if (year > 1900)
- X year -= 1900;
- X (void) sprintf(buf, "%02d%02d%02d%02d%02d%.3s",
- X year, month_to_n(month), day, hour, mins, wkday);
- X strdup(msg[cnt].m_date_recv, buf);
- X#endif /* MSG_SEPARATOR */
- X turnon(msg[cnt].m_flags, UNREAD); /* initialize */
- X
- X /* we've read the "From " line(s), now read the rest of
- X * the message headers till we get to a blank line.
- X */
- X while (fgets(buf, sizeof (buf), fp) && (*buf != '\n')) {
- X register char *p = buf;
- X if (!strncmp(buf, "Date:", 5))
- X strdup(msg[cnt].m_date_sent, parse_date(p+5));
- X if (get_status &&
- X !(get_status = strncmp(p, "Status:", 7))) {
- X /* new mail should not have a Status: field! */
- X turnon(msg[cnt].m_flags, OLD);
- X for (p += 8 ; *p != '\n'; p++)
- X switch(*p) {
- X case 'R': turnoff(msg[cnt].m_flags, UNREAD);
- X when 'P': turnon(msg[cnt].m_flags, UNREAD);
- X when 'S': turnon(msg[cnt].m_flags, SAVED);
- X when 'r': turnon(msg[cnt].m_flags, REPLIED);
- X when 'O': ; /* do nothing */
- X otherwise :
- X if (ison(glob_flags, WARNING))
- X print("unknown msg status flag: %c",*p);
- X }
- X }
- X if (isoff(glob_flags,READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X lines++;
- X }
- X if (!msg[cnt].m_date_sent || !*msg[cnt].m_date_sent)
- X if (!msg[cnt].m_date_recv || !*msg[cnt].m_date_recv) {
- X wprint("Message %d has *no* date!?\n", cnt+1);
- X msg[cnt].m_date_sent = msg[cnt].m_date_recv =
- X "0000000000XXX";
- X } else
- X strdup(msg[cnt].m_date_sent, msg[cnt].m_date_recv);
- X else if (!msg[cnt].m_date_recv || !*msg[cnt].m_date_recv)
- X strdup(msg[cnt].m_date_recv, msg[cnt].m_date_sent);
- X if (had_error)
- X break;
- X if (append && list)
- X set_msg_bit(list, cnt);
- X if (append)
- X cnt = ++msg_cnt;
- X get_status = 1;
- X }
- X }
- X if (msg_found) {
- X lines++;
- X if (isoff(glob_flags, READ_ONLY) && fputs(buf, tmpf) == -1) {
- X error(tempfile);
- X had_error++;
- X break;
- X }
- X }
- X }
- X if (msg_found && append != 1)
- X turnon(glob_flags, DO_UPDATE);
- X#ifdef MMDF
- X if (!append)
- X fputs(END_MSG_SEP, tmpf);
- X#endif /* MMDF */
- X if (had_error) {
- X if (!append)
- X msg[cnt] = old;
- X if (!msg_found && !append)
- X print("File not left in correct message format.\n");
- X } else {
- X if (append)
- X cnt--;
- X if (isoff(glob_flags, READ_ONLY))
- X msg[cnt].m_size = ftell(tmpf) - msg[cnt].m_offset;
- X else
- X msg[cnt].m_size = ftell(fp) - msg[cnt].m_offset;
- X msg[cnt].m_lines = lines;
- X /* remember where we were to seek to for when we append new mail */
- X if (append)
- X cnt++;
- X }
- X if (append)
- X msg[cnt].m_offset = ftell(fp);
- X fclose(fp);
- X if (isoff(glob_flags, READ_ONLY)) {
- X fclose(tmpf);
- X if (!(tmpf = fopen(tempfile, "r"))) {
- X error("Unable to open %s for reading", tempfile);
- X return -1;
- X }
- X }
- X return !had_error;
- X}
- END_OF_FILE
- if test 24063 -ne `wc -c <'msgs.c'`; then
- echo shar: \"'msgs.c'\" unpacked with wrong size!
- fi
- # end of 'msgs.c'
- fi
- echo shar: End of archive 11 \(of 19\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-